

.macro uart_out count,ch
    // ldr x0, =0x70000000
    // ldr x0, =0x13000000
    ldr x0, =UART_ADDR
    mov x2, \count
    mov x1, \ch
    strb w1, [x0]
    sub x2, x2, #1
    cmp x2, #0
    b.ne #-0xc
.endm

.macro calc_run_addr result, lable
    // build_base
    ldr x2, =.
    // real_base
    adr x1, #-4
    // build_label
    ldr x0, =\lable
    // build_base - build_lable
    sub x0, x2, x0
    // result = real_base - (build_base - build_lable)    
    sub \result, x1, x0
.endm

.macro simple_memcpy_64 source,target,size
    mov x0, \source
    mov x1, \target
    mov x2, \size
    sub x2, x2, #8
    ldr x4, [x0], #8
    str x4, [x1], #8
    cmp x2, #0
    b.ge #-16
.endm

.macro flush_cache addr, size
    mov x0, \addr
    mov x1, \size
    dc cvau, x0
    dsb ish
    ic ivau, x0 
    dsb ish 
    isb 
    add x0, x0, #8
    sub x1, x1, #8
    cmp x1, #0
    b.ge #-32
.endm

_start:
    // adr x3, #0
    uart_out 1, 'B'
    uart_out 1, 'L'
    uart_out 1, 'T'
    // mrs x0, S3_4_c15_c15_0
    // mov x0, #0x5b1  /* Non-secure EL0/EL1 | HVC | 64bit EL2 */
    // msr scr_el3, x0
    // msr cptr_el3, xzr   /* Disable coprocessor traps to EL3 */
    // mov x0, #0x33ff
    // msr cptr_el2, x0    /* Disable coprocessor traps to EL2 */
    // msr hstr_el2, xzr       /* Disable coprocessor traps to EL2 */
    // mov x0, #3 << 20
    // msr cpacr_el1, x0       /* Enable FP/SIMD at EL1 */

    // 设置特权指令hvc，smc有效
    // enable: b[8].HCE=1, b[7].SMD=0
    // 主要是hvc， hvc必须启用
    // mov x0, #0x5b0
    // mov x0, #0x530
    mov x0, #0x131 // a32, no-secrue
    // mov x0, #0x531  // non-secrue
    msr scr_el3, x0

    // mrs x0, cptr_el3
    // bic x0, x0, #0x1<<10 /*disable fp trap to el3*/
    // msr cptr_el3, x0

    // mrs x0, cptr_el2
    // bic x0, x0, #0x1<<10 /*disable fp trap to el2*/
    // msr cptr_el2, x0

    // msr hstr_el2, xzr       /* Disable coprocessor traps to EL2 */
    // mov x0, #3 << 20
    // msr cpacr_el1, x0       /* Enable FP/SIMD at EL1 */


    // uart_out 1, 'C'
    // 设置异常返回地址
    // calc eret abs addr 
    // calc_run_addr x0, _a64_el2
    // // calc_run_addr x0, _a64_el1h
    calc_run_addr x0, _a32_usr
    // adr x0, _a64_el3h
    msr elr_el3, x0

    // ldr x1, =0x80080000
    // adr x1, _a64_el2
    // msr elr_el3, x1
    // mov x2, #24
    // simple_memcpy_64 x0, x1, x2

    // ldr x1, =0x80080000
    // mov x2, #24
    // flush_cache x1, x2

    // mov x0, #0x0 /*enable el1 aarch32*/
    // msr hcr_el2, x0

    mov x0, #0x0 /*enable el1 aarch32*/
    msr hcr_el2, x0
    // msr SCTLR_EL1, x0
    // msr SCTLR_EL2, x0
    // msr SCTLR_EL3, x0

    // 设置异常等级， b[3:2]=el, b[1]=res0, b[0]=1:sp_elx, b[0]=0:sp_el0
    // b[5:4] = 0x1 a32 stat
    ///////////////////////////////
    // aarch32 exception level
    // M[3:0] Mode
    // 0b0000 User
    // 0b0001 FIQ
    // 0b0010 IRQ
    // 0b0011 Supervisor
    // 0b0110 Monitor
    // 0b0111 Abort
    // 0b1010 Hyp
    // 0b1011 Undefined
    // 0b1111 System
    ///////////////////////////////
    // mov x0, #0x01d3  // a32-super SPSR_svc
    // mov x0, #0x01d0 // a32-user
    // mov x0, #0x01da // a32-hyp, 
    mov x0, #0x01d6 // a32-mon
    // mov x0, #0x01df // a32-system
    // mov x0, #0x03c5 //el1h
    // mov x0, #0x03c9 // el2h
    // mov x0, 0x03cd // el3h
    // mov x0, 0x03cc // el3t
    // orr x0, x0, #0x1<<4
    msr SPSR_EL3, x0
    msr SPSR_EL2, x0
    // smc 0
    // uart_out 1, 'F'
    eret

.align 16
_a64_el3h:
    b _a64_el3h

.align 16
_a64_el2:
    // smc 0
    // 设置el1/el0执行模式（aarch32/aarch64）
    // hcr_el2[31]=1:aarch64, hcr_el2[31]=0:aarch32
    mov x0, #0x0 /*enable el1 aarch32*/
    msr hcr_el2, x0

	calc_run_addr x0, _a32_usr
    msr elr_el2, x0
    // mov x0, #0x01df // a32-system, el can change, el3 not change
    mov x0, #0x01d6 // a32-system, el can change, el3 not change
    mov x0, #0x03cd // el3h
    msr SPSR_EL2, x0
    eret 

.align 16
_a64_el1h:
    uart_out 1, 'D'
    b _a64_el1h

.align 16
_a32_usr:
#include "a32-serial-bini.S"

